﻿/*
COPYRIGHT (C) 2009 EPISERVER AB

THIS FILE IS PART OF REMOTE PAGE PROVIDER FOR EPISERVER CMS.
REMOTE PAGE PROVIDER FOR EPISERVER CMS IS FREE SOFTWARE: YOU CAN REDISTRIBUTE IT AND/OR MODIFY IT UNDER THE TERMS OF THE GNU LESSER GENERAL PUBLIC LICENSE VERSION v2.1 AS PUBLISHED BY THE FREE SOFTWARE FOUNDATION.

REMOTE PAGE PROVIDER FOR EPISERVER CMS IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU LESSER GENERAL PUBLIC LICENSE FOR MORE DETAILS.
YOU SHOULD HAVE RECEIVED A COPY OF THE GNU LESSER GENERAL PUBLIC LICENSE ALONG WITH REMOTE PAGE PROVIDER FOR EPISERVER CMS]. IF NOT, SEE <HTTP://WWW.GNU.ORG/LICENSES/>.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;
using System.ServiceModel.Security;
using System.Security.Principal;
using System.ServiceModel;
using EPiServer.DataAbstraction;
using EPiServer.Security;
using System.IO;
using EPiServer.Core;
using System.ComponentModel;
using System.ServiceModel.Channels;


namespace EPiServer.Labs.RemoteProvider
{
    public class RemoteProviderClient : IRemoteProvider 
    {
        /// <summary>
        /// Occurs when [_channel factory creating] it is common to be fired in the WCF Certificate configueration .
        /// </summary>
        private static event EventHandler<ChannelFactoryEventArgs<IRemoteProvider>> _channelFactoryCreating;
        private event EventHandler      _communicationOpenedEvent;
        private event EventHandler      _communicationClosedEvent;

        /// <summary>
        /// The WCF Channel
        /// </summary>
        IRemoteProvider                 _RemoteProviderProxy = null;

        /// <summary>
        /// The WCF Channel Factory
        /// </summary>
        ChannelFactory<IRemoteProvider> _RemoteProviderChannel;

        /// <summary>
        /// The customer channel factory. It's be substituted with the _RemoteProviderChannel
        /// It uses when the Cetificate uses
        /// </summary>
        ChannelFactory<IRemoteProvider> _customPageProviderChannel;
        InitializeData                  _initializeData;
        
        string                          _endpoint;
        bool                            _inited;
        private object                  _lockObject = new Object();

        /// <summary>
        /// Application credentials
        /// </summary>
        string                          _proxyUserName = string.Empty;
        string                          _proxyPassword = string.Empty;

        #region constructure
        /// <summary>
        /// Initializes a new instance of the <see cref="RemoteProviderClient"/> class.
        /// </summary>
        /// <param name="endpoint">The endpoint.</param>
        /// <param name="initializeData">The initialize data.</param>
        public RemoteProviderClient(string endpoint, InitializeData initializeData)
        {
            _endpoint = endpoint;
            _initializeData = initializeData;
            _RemoteProviderChannel = new ChannelFactory<IRemoteProvider>(endpoint);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="RemoteProviderClient"/> class.
        /// </summary>
        /// <param name="endpoint">The endpoint.</param>
        /// <param name="proxyUserName">Name of the proxy user.</param>
        /// <param name="proxyPassword">The proxy password.</param>
        /// <param name="initializeData">The initialize data.</param>
        public RemoteProviderClient(string endpoint, string proxyUserName, string proxyPassword, InitializeData initializeData)
        {
            _endpoint = endpoint;
            _initializeData = initializeData;
            _proxyUserName = proxyUserName;
            _proxyPassword = proxyPassword;
            _RemoteProviderChannel = new ChannelFactory<IRemoteProvider>(endpoint);
        }

        #endregion

        #region Internal Methods
        /// <summary>
        /// Creates the channel factory.
        /// </summary>
        private void CreateChannelFactory()
        {

            _RemoteProviderChannel = new ChannelFactory<IRemoteProvider>(_endpoint);
            SetProxyCredentials();
            if (_channelFactoryCreating != null)
            {
                ChannelFactoryEventArgs<IRemoteProvider> channelFactoryArgs = new ChannelFactoryEventArgs<IRemoteProvider>(_RemoteProviderChannel);
                _channelFactoryCreating(this, channelFactoryArgs);
                _customPageProviderChannel = channelFactoryArgs.ChannelFactory;
                _RemoteProviderChannel = channelFactoryArgs.ChannelFactory;
            }
            _RemoteProviderChannel.Faulted += new EventHandler(RemoteProviderChannel_Faulted);
            _RemoteProviderChannel.Closed += new EventHandler(RemoteProviderChannel_Closed);
            _RemoteProviderProxy = _RemoteProviderChannel.CreateChannel();
        }

        /// <summary>
        /// Sets the proxy credentials.
        /// </summary>
        private void SetProxyCredentials()
        {
            _RemoteProviderChannel.Credentials.UserName.UserName = _proxyUserName;
            _RemoteProviderChannel.Credentials.UserName.Password = _proxyPassword;
        }

        /// <summary>
        /// Initeds this instance.
        /// </summary>
        private void Inited()
        {
            if (!_inited)
            {
                lock (_lockObject)
                {
                    if (!_inited)
                    {
                        CreateChannelFactory();
                        Init();
                    }
                }
            }
        }

        /// <summary>
        /// Inits this instance.
        /// </summary>
        private void Init()
        {
            try
            {
                _RemoteProviderProxy.Initialize(ref _initializeData);
                _inited = true;
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
        }
        #endregion

        #region Communication Event Handling
        public  event EventHandler CommunicationOpened
        {
            add
            {
                _communicationOpenedEvent += value;
            }
            remove
            {
                _communicationOpenedEvent -= value;
            }
        }

        public event EventHandler CommunicationClosed
        {
            add
            {
                _communicationClosedEvent += value;
            }
            remove
            {
                _communicationClosedEvent -= value;
            }
        }
        #endregion

        #region Error Handling

        /// <summary>
        /// Closes the communication.
        /// </summary>
        private void CloseCommunication()
        {
            if (_RemoteProviderChannel != null)
            {
                _RemoteProviderChannel.Abort();
                _RemoteProviderChannel.Close();
                _RemoteProviderChannel = null;
            }
            _RemoteProviderProxy = null;
            _inited = false;

            if (_communicationClosedEvent != null)
            {
                _communicationClosedEvent(this, new EventArgs());
            }
        }

        /// <summary>
        /// Handles the appplication exception.
        /// </summary>
        /// <param name="RemoteProviderFaultException">The remote page provider fault exception.</param>
        private void HandleAppplicationException(FaultException<RemoteProviderFault> remoteProviderFaultException)
        {
            throw remoteProviderFaultException;
        }

        /// <summary>
        /// Handles the communication exception.
        /// </summary>
        /// <param name="communicationEx">The communication ex.</param>
        private void HandleCommunicationException(CommunicationException communicationEx)
        {
            CloseCommunication();
            throw communicationEx;
        }

        /// <summary>
        /// Handles the appplication exception.
        /// </summary>
        /// <param name="faultException">The fault exception.</param>
        private void HandleAppplicationException(FaultException faultException)
        {
            //What should we do, treate as Application Level?
            // Should close the new WCF channel or ????
            CloseCommunication();
            throw faultException;
        }

        /// <summary>
        /// Handles the exception.
        /// </summary>
        /// <param name="ex">The ex.</param>
        private void HandleException(Exception ex)
        {
            //What should we do, treate as Application Level?
            // Should close the new WCF channel or ????
            CloseCommunication();
            throw ex;
        }
        #endregion

        #region Channel Factory Create Event
        /// <summary>
        /// Occurs when [channel factory creating].
        /// </summary>
        public static event EventHandler<ChannelFactoryEventArgs<IRemoteProvider>> ChannelFactoryCreating
        {
            add
            {
                _channelFactoryCreating += value;
            }
            remove
            {
                _channelFactoryCreating -= value;
            }
        }
        #endregion

        #region Channel Events

        /// <summary>
        /// Handles the Faulted event of the RemoteProviderChannel control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        void RemoteProviderChannel_Faulted(object sender, EventArgs e)
        {
            _inited = false;
        }

        /// <summary>
        /// Handles the Closed event of the RemoteProviderChannel control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        void RemoteProviderChannel_Closed(object sender, EventArgs e)
        {
            _inited = false;
        }
        #endregion

        #region IRemoteProvider Members

        /// <summary>
        /// Initializes the specified initialize data.
        /// </summary>
        /// <param name="initializeData">The initialize data.</param>
        public void Initialize(ref InitializeData initializeData)
        {
            try
            {
                Inited();
                initializeData = _initializeData;
                if (_communicationOpenedEvent != null)
                {
                    _communicationOpenedEvent(this, new EventArgs());
                }
            }
            catch (Exception)
            {
                _inited = false;
            }
        }

        /// <summary>
        /// Gets the children references.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <returns>
        /// PageReferenceCollection which is children's pagereference
        /// </returns>
        public PageReferenceCollection GetChildrenReferences(PageReference pageLink)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.GetChildrenReferences(pageLink);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Gets the pages.
        /// </summary>
        /// <param name="pageLinks">The page links.</param>
        /// <param name="selector">The selector.</param>
        /// <returns>
        /// RemotePageRaw[] which is an array of light version of PageData raw data
        /// </returns>
        public RemotePageRaw[] GetPages(PageReferenceCollection pageLinks, LanguageSelector selector)
        {
            Inited();
            try
            {
                return GetPages(pageLinks, selector);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Gets the page.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <param name="selector">The selector.</param>
        /// <returns>
        /// RemotePageRaw which is a light version of PageData raw data
        /// </returns>
        public RemotePageRaw GetPage(PageReference pageLink, LanguageSelector selector)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.GetPage(pageLink, selector);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }
        /// <summary>
        /// Get collection of references to these pages
        /// </summary>
        /// <param name="pageLinks"></param>
        /// <returns></returns>
        public PageReferenceCollection GetReferencesToPages(PageReferenceCollection pageLinks)
        {
            try 
            {
                return _RemoteProviderProxy.GetReferencesToPages(pageLinks);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Finds the pages with criteria.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <param name="criterias">The criterias.</param>
        /// <param name="languageBranch">The language branch.</param>
        /// <param name="selector">The selector.</param>
        /// <returns>
        /// RemotePageRaw which is a light version of PageData raw data
        /// </returns>
        public RemotePageRaw[] FindPagesWithCriteria(PageReference pageLink, PropertyCriteriaCollection criterias, string languageBranch, LanguageSelector selector)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.FindPagesWithCriteria(pageLink, criterias, languageBranch, selector);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Gets the language branches.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <returns>
        /// RemotePageRaw which is a light version of PageData raw data
        /// </returns>
        public RemotePageRaw[] GetLanguageBranches(PageReference pageLink)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.GetLanguageBranches(pageLink);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Creates the language branch.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <param name="selector">The selector.</param>
        /// <returns>
        /// RemotePageRaw which is a light version of PageData raw data
        /// </returns>
        public RemotePageRaw CreateLanguageBranch(PageReference pageLink, LanguageSelector selector)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.CreateLanguageBranch(pageLink, selector);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Deletes the language branch.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <param name="languageBranch">The language branch.</param>
        public void DeleteLanguageBranch(PageReference pageLink, string languageBranch)
        {
            Inited();
            try
            {
                _RemoteProviderProxy.DeleteLanguageBranch(pageLink, languageBranch);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
        }

        /// <summary>
        /// Deletes the version.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        public void DeleteVersion(PageReference pageLink)
        {
            Inited();
            try
            {
                _RemoteProviderProxy.DeleteVersion(pageLink);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
        }

        /// <summary>
        /// Deletes the specified page link.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <param name="forceDelete">if set to <c>true</c> [force delete].</param>
        public void Delete(PageReference pageLink, bool forceDelete)
        {
            Inited();
            try
            {
                _RemoteProviderProxy.Delete(pageLink, forceDelete);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
        }

        /// <summary>
        /// Deletes the children.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <param name="forceDelete">if set to <c>true</c> [force delete].</param>
        public void DeleteChildren(PageReference pageLink, bool forceDelete)
        {
            Inited();
            try
            {
                _RemoteProviderProxy.DeleteChildren(pageLink, forceDelete);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
        }

        /// <summary>
        /// Moves the specified page link.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <param name="destinationLink">The destination link.</param>
        public void Move(PageReference pageLink, PageReference destinationLink)
        {
            Inited();
            try
            {
                _RemoteProviderProxy.Move(pageLink, destinationLink);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
        }

        /// <summary>
        /// Moves to wastebasket.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        public void MoveToWastebasket(PageReference pageLink)
        {
            Inited();
            try
            {
                _RemoteProviderProxy.MoveToWastebasket(pageLink);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
        }

        /// <summary>
        /// Copies the specified page link.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <param name="destinationLink">The destination link.</param>
        /// <param name="publishOnDestination">if set to <c>true</c> [publish on destination].</param>
        /// <param name="allowThreading">if set to <c>true</c> [allow threading].</param>
        /// <returns></returns>
        public PageReference Copy(PageReference pageLink, PageReference destinationLink, bool publishOnDestination, bool allowThreading)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.Copy(pageLink, destinationLink, publishOnDestination, allowThreading);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Saves the specified page.
        /// </summary>
        /// <param name="page">The page.</param>
        /// <param name="action">The action.</param>
        /// <param name="IsModified">Indicates if the page is modified</param>
        /// <returns></returns>
        public PageReference Save(RemotePageRaw page, int action, bool IsModified)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.Save(page, action, IsModified);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Resolves the page from page GUID.
        /// </summary>
        /// <param name="pageGuid">The page GUID.</param>
        /// <param name="pageLink">The page link.</param>
        /// <returns>PageTypeName</returns>
        public string ResolvePageFromPageGuid(Guid pageGuid, out PageReference pageLink)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.ResolvePageFromPageGuid(pageGuid, out pageLink);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }

            pageLink = PageReference.EmptyReference;
            return string.Empty;
        }

        /// <summary>
        /// Resolves the page from page link.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <param name="pageGuid">The page GUID.</param>
        /// <returns>PageTypeName</returns>
        public string ResolvePageFromPageLink(PageReference pageLink, out Guid pageGuid)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.ResolvePageFromPageLink(pageLink, out pageGuid);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            pageGuid = Guid.Empty;
            return string.Empty;
        }

        /// <summary>
        /// Lists the versions.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <param name="languageBranch">The language branch.</param>
        /// <returns></returns>
        public PageVersionCollection ListVersions(PageReference pageLink, string languageBranch)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.ListVersions(pageLink, languageBranch);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Lists the published versions.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <returns></returns>
        public PageVersionCollection ListPublishedVersions(PageReference pageLink)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.ListPublishedVersions(pageLink);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Loads the version.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <returns></returns>
        public PageVersion LoadVersion(PageReference pageLink)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.LoadVersion(pageLink);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Loads the published version.
        /// </summary>
        /// <param name="pageLink">The page link.</param>
        /// <param name="languageBranch">The language branch.</param>
        /// <returns></returns>
        public PageVersion LoadPublishedVersion(PageReference pageLink, string languageBranch)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.LoadPublishedVersion(pageLink, languageBranch);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Lists the delayed publish.
        /// </summary>
        /// <returns></returns>
        public RemotePageRaw[] ListDelayedPublish()
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.ListDelayedPublish();
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        #endregion

        #region Remote  File Provider Members

        /// <summary>
        /// Initializes the virtual path proivder.
        /// </summary>
        /// <param name="remoteVirtualProvidersInfo">The remote virtual providers info.</param>
        public void InitializeVirtualPathProivder(ref RemoteVirtualPathProvidersInfo remoteVirtualProvidersInfo)
        {
            Inited();
            try
            {
                _RemoteProviderProxy.InitializeVirtualPathProivder(ref remoteVirtualProvidersInfo);
                _initializeData.RemoteVirtualPathProvidersInfo = remoteVirtualProvidersInfo;
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return;
        }

        /// <summary>
        /// Gets the file.
        /// </summary>
        /// <param name="virtualPath">The virtual path.</param>
        /// <param name="remoteFileInfo">The remote file info.</param>
        /// <returns></returns>
        public bool GetFile(string virtualPath, out RemoteFileInfo remoteFileInfo)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.GetFile(virtualPath, out remoteFileInfo);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            remoteFileInfo = null;
            return false;
        }

        /// <summary>
        /// Gets the directory.
        /// </summary>
        /// <param name="virtualPath">The virtual path.</param>
        /// <param name="remoteDirectoryInfo">The remote directory info.</param>
        /// <returns></returns>
        public bool GetDirectory(string virtualPath, out RemoteDirectoryInfo remoteDirectoryInfo)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.GetDirectory(virtualPath, out remoteDirectoryInfo);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            remoteDirectoryInfo = null;
            return false;
        }

        /// <summary>
        /// Files the exists.
        /// </summary>
        /// <param name="virtualPath">The virtual path.</param>
        /// <returns></returns>
        public bool FileExists(string virtualPath)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.FileExists(virtualPath);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return false;
        }

        /// <summary>
        /// Directories the exists.
        /// </summary>
        /// <param name="virtualPath">The virtual path.</param>
        /// <returns></returns>
        public bool DirectoryExists(string virtualPath)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.DirectoryExists(virtualPath);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return false;
        }

        /// <summary>
        /// Opens the specified virtual path.
        /// </summary>
        /// <param name="virtualPath">The virtual path.</param>
        /// <param name="remoteFileInfo">The remote file info.</param>
        public void Open(string virtualPath, out RemoteFileInfo remoteFileInfo)
        {
            Inited();
            try
            {
                _RemoteProviderProxy.Open(virtualPath, out remoteFileInfo);
                return;
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }

            remoteFileInfo = new RemoteFileInfo();
            return;
        }

        /// <summary>
        /// Directorieses the specified virtual path.
        /// </summary>
        /// <param name="virtualPath">The virtual path.</param>
        /// <returns></returns>
        public RemoteDirectoryInfo[] Directories(string virtualPath)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.Directories(virtualPath);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Fileses the specified virtual path.
        /// </summary>
        /// <param name="virtualPath">The virtual path.</param>
        /// <returns></returns>
        public RemoteFileInfo[] Files(string virtualPath)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.Files(virtualPath);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Resolves the file by GUID.
        /// </summary>
        /// <param name="guid">The GUID.</param>
        /// <returns></returns>
        public string ResolveFileByGuid(Guid guid)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.ResolveFileByGuid(guid);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return null;
        }

        /// <summary>
        /// Resolves the file by virtual path.
        /// </summary>
        /// <param name="virtualPath">The virtual path.</param>
        /// <param name="guid">The GUID.</param>
        /// <returns></returns>
        public string ResolveFileByVirtualPath(string virtualPath, out Guid guid)
        {
            Inited();
            try
            {
                return _RemoteProviderProxy.ResolveFileByVirtualPath(virtualPath, out guid);
            }
            catch (FaultException<RemoteProviderFault> remmotePageProviderFaultException)
            {
                HandleAppplicationException(remmotePageProviderFaultException);
            }
            catch (FaultException faultException)
            {
                HandleAppplicationException(faultException);
            }
            catch (CommunicationException communicationEx)
            {
                HandleCommunicationException(communicationEx);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            guid = Guid.Empty;
            return null;
        }

        #endregion


        /// <summary>
        /// Gets the state of the communication.
        /// </summary>
        /// <returns></returns>
        public CommunicationState GetCommunicationState()
        {
            if (_RemoteProviderChannel != null)
            {
                return _RemoteProviderChannel.State;
            }
            return CommunicationState.Closed;
        }


    }

}
